﻿Imports System.Text
Imports System.IO
Imports System.Xml.Serialization
Imports System.Xml
Imports System.Collections.ObjectModel

Namespace Microsoft.VisualStudio.RegularExpression.UI
	''' <summary>
	''' 
	''' </summary>
	Friend Class RegexRepositoryService
        Private Const RepositoryPath = "expressions.xml"
		Private repositoryFile As String
        Private mItems As ObservableCollection(Of RegexRepositoryItem)
        Private mFilteredItems As ObservableCollection(Of RegexRepositoryItem)

        Friend Sub New()
            Me.New(Path.Combine(Path.GetDirectoryName(GetType(RegexRepositoryService).Assembly.Location), RepositoryPath))
        End Sub

        Friend Sub New(ByVal repositoryFile As String)
            Me.New(repositoryFile, False)
        End Sub

        Friend Sub New(ByVal repositoryFile As String, ByVal throwOnFailure As Boolean)
            Me.repositoryFile = repositoryFile

            Try
                Me.LoadItems()
                Me.mFilteredItems = New ObservableCollection(Of RegexRepositoryItem)
                For Each item As RegexRepositoryItem In mItems
                    mFilteredItems.Add(item)
                Next item
            Catch
                Me.mItems = New ObservableCollection(Of RegexRepositoryItem)

                If throwOnFailure Then
                    Throw
                End If
            End Try
        End Sub

        Private Sub EnsureRepositoryFile()
            If File.Exists(Me.repositoryFile) Then
                If (File.GetAttributes(Me.repositoryFile) And FileAttributes.ReadOnly) <> 0 Then
                    File.SetAttributes(Me.repositoryFile, FileAttributes.Normal)
                End If
            Else
                Dim myPath = Path.GetDirectoryName(Me.repositoryFile)

                If Not Directory.Exists(myPath) Then
                    Directory.CreateDirectory(myPath)
                End If
            End If
        End Sub

        Private Sub SaveItems()
            EnsureRepositoryFile()

            Dim serializer As New XmlSerializer(GetType(List(Of RegexRepositoryItem)))
            Dim settings As New XmlWriterSettings
            settings.Indent = True

            Using stream As New FileStream(Me.repositoryFile, FileMode.Create, FileAccess.Write)
                Using writer = XmlWriter.Create(stream, settings)
                    serializer.Serialize(writer, Me.mItems.ToList())
                End Using
            End Using
        End Sub

        Private Sub LoadItems()
            If File.Exists(Me.repositoryFile) Then
                Dim serializer As New XmlSerializer(GetType(List(Of RegexRepositoryItem)))

                Using stream As New FileStream(Me.repositoryFile, FileMode.Open, FileAccess.Read)
                    Using reader = XmlReader.Create(stream)
                        Me.mItems = New ObservableCollection(Of RegexRepositoryItem)(TryCast(serializer.Deserialize(reader), List(Of RegexRepositoryItem)))
                    End Using
                End Using
            Else
                Me.mItems = New ObservableCollection(Of RegexRepositoryItem)
            End If
        End Sub


        Private mFilter As String

        Public Property Filter As String
            Get
                Return mFilter
            End Get
            Set(ByVal value As String)
                mFilter = value
                UpdateFilteredItems()
            End Set
        End Property

        Private Sub UpdateFilteredItems()
            If Me.mFilteredItems IsNot Nothing Then
                Me.mFilteredItems.Clear()

                For Each item As RegexRepositoryItem In mItems
                    If mFilter = String.Empty OrElse (item.Title.ToUpper().Contains(Filter.ToUpper()) OrElse item.Description.ToUpper().Contains(Filter.ToUpper())) Then
                        mFilteredItems.Add(item)
                    End If
                Next item
            End If
        End Sub

        ''' <summary>
        ''' 
        ''' </summary>
        Public ReadOnly Property Items As IEnumerable(Of RegexRepositoryItem)
            Get
                Return Me.mItems
            End Get
        End Property

        Public ReadOnly Property FilteredItems As IEnumerable(Of RegexRepositoryItem)
            Get
                Return Me.mFilteredItems
            End Get
        End Property

        Friend Function CreateItem(ByVal name As String, ByVal regex As String) As RegexRepositoryItem
            Return New RegexRepositoryItem With {.Author = Environment.UserName, .Category = "default", .Title = name, .Description = name, .Matches = String.Empty, .Regex = regex}
        End Function

        Friend Sub Save(ByVal item As RegexRepositoryItem)
            If Not Me.mItems.Contains(item) Then
                Me.mItems.Add(item)
            End If

            SaveItems()
        End Sub

        Friend Sub Delete(ByVal item As RegexRepositoryItem)
            If Me.mItems.Contains(item) Then
                Me.mItems.Remove(item)
            End If

            SaveItems()
        End Sub

        Friend Sub GenerateUniqueTitle(ByVal item As RegexRepositoryItem)
            item.Title = GenerateUniqueName(Function(title) Me.mItems.Where(Function(i) String.Compare(i.Title, title, True) = 0).Count() = 0, item.Title, 1)
        End Sub

		Friend Function GenerateUniqueName(ByVal uniqueNamePredicate As Predicate(Of String), ByVal name As String, ByVal index As Integer) As String
            Dim uniqueName = name & index.ToString()
			If uniqueNamePredicate(uniqueName) Then
				Return uniqueName
			Else
				index += 1
				Return GenerateUniqueName(uniqueNamePredicate, name, index)
			End If
		End Function
	End Class
End Namespace